package com.example.controlcarappv2;

import java.util.ArrayList;
import java.util.List;

public class algoritmoSolucao {

	// Heuristica
	boolean resolvido = false;
	List<Labirinto> openList = new ArrayList<Labirinto>();
	List<Labirinto> closedList = new ArrayList<Labirinto>();
	Labirinto ultimo = null;

	void resolveLabirinto(Labirinto labirinto) {

		openList.add(labirinto);

		while (!resolvido) {

			// Se a lista esta vazia nao funciona.
			if (openList.isEmpty()) {
				System.out.println(" Nao soluvel ");
				break;
			}

			// Pega o no com menor heuristica.
			Labirinto melhor = algoritmoSolucao
					.retornaMenorHeuristica(openList);

			// Retira o no da lista.
			if (openList.contains(melhor))
				openList.remove(melhor);

			if (!closedList.contains(melhor))
				closedList.add(melhor);

			// Verifica se e o estado desejado.
			if (melhor.iH == 0) {
				ultimo = melhor;
				resolvido = true;
			}

			// Verifica os adjacentes e adiciona na OpenList
			for (Acao a : melhor.acoesPossiveis()) {

				Labirinto sucessor = melhor.executaAcao(a);

				if (algoritmoSolucao.checarClosedPositions(closedList,
						sucessor.iPosicao[0], sucessor.iPosicao[1])) {
					continue;
				}

				Labirinto antigo = algoritmoSolucao.checarOpenPositions(
						openList, sucessor.iPosicao[0], sucessor.iPosicao[1]);

				if (antigo != null) {
					if (sucessor.iG < antigo.iG) {
						sucessor.anterior = antigo.anterior;
						sucessor.acaoRealizada = a;
						sucessor.iG = melhor.iG
								+ algoritmoSolucao.distancia(melhor, sucessor);
						sucessor.iF = sucessor.iG + sucessor.iH;
						continue;
					}
				}

				sucessor.anterior = melhor;
				sucessor.acaoRealizada = a;
				sucessor.iG = melhor.iG
						+ algoritmoSolucao.distancia(melhor, sucessor);
				sucessor.iF = sucessor.iG + sucessor.iH;

				openList.add(sucessor);

			}
		}
	}

	public static Labirinto retornaMenorHeuristica(List<Labirinto> lab) {

		Labirinto retorna = null;

		if (lab.size() > 0) {
			retorna = lab.get(lab.size() - 1);
		}

		for (int i = 0; i < lab.size(); i++) {
			if (lab.get(i).iF <= retorna.iF)
				retorna = lab.get(i);
		}

		return retorna;
	}

	public static boolean checarClosedPositions(List<Labirinto> closedList,
			int posicaox, int posicaoy) {
		for (Labirinto lab : closedList) {
			if (lab.iPosicao[0] == posicaox && lab.iPosicao[1] == posicaoy)
				return true;
		}
		return false;
	}

	public static Labirinto checarOpenPositions(List<Labirinto> openList,
			int posicaox, int posicaoy) {

		Labirinto retorna = null;

		for (Labirinto lab : openList) {
			if (lab.iPosicao[0] == posicaox && lab.iPosicao[1] == posicaoy)
				retorna = lab;
		}

		return retorna;
	}

	public static int distancia(Labirinto atual, Labirinto destino) {

		int retorna = Math.abs(atual.iPosicao[0] - destino.iPosicao[0])
				+ Math.abs(atual.iPosicao[1] - destino.iPosicao[1]);

		return retorna;
	}
}